home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #3 / Amiga Plus CD - 2002 - No. 03.iso / AmiSoft / Hard / Drivr / 3c589.lha / 3c589 / Source / device.c next >
C/C++ Source or Header  |  2003-02-08  |  12KB  |  653 lines

  1. /*
  2.  
  3. File: device.c
  4. Author: Neil Cafferkey
  5. Copyright (C) 2000-2003 Neil Cafferkey
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  20. MA 02111-1307, USA.
  21.  
  22. */
  23.  
  24.  
  25. #include <exec/types.h>
  26. #include <exec/resident.h>
  27. #include <exec/errors.h>
  28. #include <utility/utility.h>
  29. #include "initializers.h"
  30.  
  31. #include <proto/exec.h>
  32. #include <proto/alib.h>
  33. #include <proto/utility.h>
  34.  
  35. #include "device.h"
  36.  
  37. #include "unit_protos.h"
  38. #include "request_protos.h"
  39.  
  40. #define VERSION 1
  41. #define REVISION 3
  42. #define UNIT_COUNT 1
  43. #define UTILITY_VERSION 36
  44. #define PCCARD_VERSION 1
  45.  
  46.  
  47. /* Private prototypes */
  48.  
  49. static struct DevBase *DevInit(struct DevBase *dev_base REG("d0"),
  50.    APTR seg_list REG("a0"),struct DevBase *base REG(BASE_REG));
  51. static BYTE DevOpen(ULONG unit_no REG("d0"),
  52.    struct IOSana2Req *request REG("a1"),ULONG flags REG("d1"),
  53.    struct DevBase *base REG(BASE_REG));
  54. static APTR DevClose(struct IOSana2Req *request REG("a1"),
  55.    struct DevBase *base REG(BASE_REG));
  56. static APTR DevExpunge(struct DevBase *base REG(BASE_REG));
  57. static APTR DevReserved();
  58. static VOID DevBeginIO(struct IOSana2Req *request REG("a1"),
  59.    struct DevBase *base REG(BASE_REG));
  60. static VOID DevAbortIO(struct IORequest *request REG("a1"),
  61.    struct DevBase *base REG(BASE_REG));
  62. VOID DeleteDevice(struct DevBase *base);
  63.  
  64. extern const APTR vectors[];
  65. extern const APTR init_table[];
  66.  
  67.  
  68. /* Return an error immediately if someone tries to run the device */
  69.  
  70. LONG Main()
  71. {
  72.    return -1;
  73. }
  74.  
  75. #define DEVICE_NAME "3c589.device"
  76.  
  77. const TEXT device_name[]=DEVICE_NAME;
  78. static const TEXT version_string[]=DEVICE_NAME " 1.3 (8.2.2003)\n";
  79. static const TEXT card_name[]=CARDRESNAME;
  80. static const TEXT utility_name[]=UTILITYNAME;
  81. static const TEXT pccard_name[]=PCCARDNAME;
  82. static const TEXT timer_name[]=TIMERNAME;
  83.  
  84.  
  85. const struct Resident device_rom_tag=
  86. {
  87.    RTC_MATCHWORD,
  88.    (struct Resident *)&device_rom_tag,
  89.    (APTR)init_table,
  90.    RTF_AUTOINIT,
  91.    VERSION,
  92.    NT_DEVICE,
  93.    0,
  94.    (STRPTR)device_name,
  95.    (STRPTR)version_string,
  96.    (APTR)init_table
  97. };
  98.  
  99.  
  100. static const APTR vectors[]=
  101. {
  102.    (APTR)DevOpen,
  103.    (APTR)DevClose,
  104.    (APTR)DevExpunge,
  105.    (APTR)DevReserved,
  106.    (APTR)DevBeginIO,
  107.    (APTR)DevAbortIO,
  108.    (APTR)-1
  109. };
  110.  
  111.  
  112. static const struct
  113. {
  114.    SMALLINITBYTEDEF(type);
  115.    SMALLINITPINTDEF(name);
  116.    SMALLINITBYTEDEF(flags);
  117.    SMALLINITWORDDEF(version);
  118.    SMALLINITWORDDEF(revision);
  119.    SMALLINITPINTDEF(id_string);
  120.    INITENDDEF;
  121. }
  122. init_data=
  123. {
  124.    SMALLINITBYTE(OFFSET(Node,ln_Type),NT_DEVICE),
  125.    SMALLINITPINT(OFFSET(Node,ln_Name),device_name),
  126.    SMALLINITBYTE(OFFSET(Library,lib_Flags),LIBF_SUMUSED|LIBF_CHANGED),
  127.    SMALLINITWORD(OFFSET(Library,lib_Version),VERSION),
  128.    SMALLINITWORD(OFFSET(Library,lib_Revision),REVISION),
  129.    SMALLINITPINT(OFFSET(Library,lib_IdString),version_string),
  130.    INITEND
  131. };
  132.  
  133.  
  134. static const APTR init_table[]=
  135. {
  136.    (APTR)sizeof(struct DevBase),
  137.    (APTR)vectors,
  138.    (APTR)&init_data,
  139.    (APTR)DevInit
  140. };
  141.  
  142.  
  143. static const ULONG rx_tags[]=
  144. {
  145.    S2_CopyToBuff,
  146.    S2_CopyToBuff16,
  147.    S2_CopyToBuff32
  148. };
  149.  
  150.  
  151. static const ULONG tx_tags[]=
  152. {
  153.    S2_CopyFromBuff,
  154.    S2_CopyFromBuff16,
  155.    S2_CopyFromBuff32
  156. };
  157.  
  158.  
  159.  
  160. /****i* 3c589.device/DevInit ***********************************************
  161. *
  162. *   NAME
  163. *    DevInit -- .
  164. *
  165. *   SYNOPSIS
  166. *    dev_base = DevInit(dev_base,seg_list)
  167. *
  168. *    struct DevBase *DevInit(struct DevBase *,APTR);
  169. *
  170. *   FUNCTION
  171. *
  172. *   INPUTS
  173. *
  174. *   RESULT
  175. *
  176. *   EXAMPLE
  177. *
  178. *   NOTES
  179. *
  180. *   BUGS
  181. *
  182. *   SEE ALSO
  183. *
  184. ****************************************************************************
  185. *
  186. */
  187.  
  188. static struct DevBase *DevInit(struct DevBase *dev_base REG("d0"),
  189.    APTR seg_list REG("a0"),struct DevBase *base REG(BASE_REG))
  190. {
  191.    BOOL success=TRUE;
  192.  
  193.    dev_base->sys_base=(APTR)base;
  194.    base=dev_base;
  195.    base->seg_list=seg_list;
  196.  
  197.    base->card_base=OpenResource(card_name);
  198.    base->utility_base=(APTR)OpenLibrary(utility_name,UTILITY_VERSION);
  199.    base->pccard_base=OpenLibrary(pccard_name,PCCARD_VERSION);
  200.    if((base->card_base==NULL)||(base->utility_base==NULL)||
  201.       (base->pccard_base==NULL))
  202.       success=FALSE;
  203.  
  204.    if(OpenDevice(timer_name,UNIT_VBLANK,(APTR)&base->timer_request,0)!=0)
  205.       success=FALSE;
  206.  
  207.    NewList((APTR)(&dev_base->units));
  208.  
  209.    if(!success)
  210.    {
  211.       DeleteDevice(base);
  212.       base=NULL;
  213.    }
  214.  
  215.    return base;
  216. }
  217.  
  218.  
  219.  
  220. /****i* 3c589.device/DevOpen ***********************************************
  221. *
  222. *   NAME
  223. *    DevOpen -- .
  224. *
  225. *   SYNOPSIS
  226. *    error = DevOpen(unit_num,request,flags)
  227. *
  228. *    BYTE DevOpen(ULONG,struct IOSana2Req *,ULONG);
  229. *
  230. *   FUNCTION
  231. *
  232. *   INPUTS
  233. *
  234. *   RESULT
  235. *
  236. *   EXAMPLE
  237. *
  238. *   NOTES
  239. *
  240. *   BUGS
  241. *
  242. *   SEE ALSO
  243. *
  244. ****************************************************************************
  245. *
  246. */
  247.  
  248. static BYTE DevOpen(ULONG unit_num REG("d0"),
  249.    struct IOSana2Req *request REG("a1"),ULONG flags REG("d1"),
  250.    struct DevBase *base REG(BASE_REG))
  251. {
  252.    struct DevUnit *unit;
  253.    BYTE error=0;
  254.    struct Opener *opener;
  255.    struct TagItem *tag_list;
  256.    UWORD i;
  257.  
  258.    base->device.dd_Library.lib_OpenCnt++;
  259.    base->device.dd_Library.lib_Flags&=~LIBF_DELEXP;
  260.  
  261.    request->ios2_Req.io_Unit=NULL;
  262.    tag_list=request->ios2_BufferManagement;
  263.    request->ios2_BufferManagement=NULL;
  264.  
  265.    /* Check request size and unit number */
  266.  
  267.    if((request->ios2_Req.io_Message.mn_Length<sizeof(struct IOSana2Req))
  268.       ||(unit_num>=UNIT_COUNT))
  269.       error=IOERR_OPENFAIL;
  270.  
  271.    /* Get the requested unit */
  272.  
  273.    if(error==0)
  274.    {
  275.       request->ios2_Req.io_Unit=(APTR)unit=GetUnit(unit_num,base);
  276.       if(unit==NULL)
  277.          error=IOERR_OPENFAIL;
  278.    }
  279.  
  280.    /* Handle device sharing */
  281.  
  282.    if(error==0)
  283.    {
  284.       if((unit->open_count!=0)&&(((unit->flags&UNITF_SHARED)==0)||
  285.          ((flags&SANA2OPF_MINE)!=0)))
  286.          error=IOERR_UNITBUSY;
  287.       unit->open_count++;
  288.    }
  289.  
  290.    if(error==0)
  291.    {
  292.       if((flags&SANA2OPF_MINE)==0)
  293.          unit->flags|=UNITF_SHARED;
  294.       else if((flags&SANA2OPF_PROM)!=0)
  295.          unit->flags|=UNITF_PROM;
  296.  
  297.       /* Set up buffer-management structure and get hooks */
  298.  
  299.       request->ios2_BufferManagement=opener=
  300.          AllocVec(sizeof(struct Opener),MEMF_PUBLIC);
  301.       if(opener==NULL)
  302.          error=IOERR_OPENFAIL;
  303.    }
  304.  
  305.    if(error==0)
  306.    {
  307.       NewList(&opener->read_port.mp_MsgList);
  308.       opener->read_port.mp_Flags=PA_IGNORE;
  309.       NewList((APTR)&opener->initial_stats);
  310.  
  311.       for(i=0;i<2;i++)
  312.          opener->rx_function=(APTR)GetTagData(rx_tags[i],
  313.             (UPINT)opener->rx_function,tag_list);
  314.       for(i=0;i<3;i++)
  315.          opener->tx_function=(APTR)GetTagData(tx_tags[i],
  316.             (UPINT)opener->tx_function,tag_list);
  317.  
  318.       opener->filter_hook=(APTR)GetTagData(S2_PacketFilter,NULL,tag_list);
  319.       opener->dma_tx_function=
  320.          (APTR)GetTagData(S2_DMACopyFromBuff32,NULL,tag_list);
  321.  
  322.       Disable();
  323.       AddTail((APTR)&unit->openers,(APTR)opener);
  324.       Enable();
  325.    }
  326.  
  327.    /* Back out if anything went wrong */
  328.  
  329.    if(error!=0)
  330.       DevClose(request,base);
  331.  
  332.    /* Return */
  333.  
  334.    request->ios2_Req.io_Error=error;
  335.    return error;
  336. }
  337.  
  338.  
  339.  
  340. /****i* 3c589.device/DevClose **********************************************
  341. *
  342. *   NAME
  343. *    DevClose -- .
  344. *
  345. *   SYNOPSIS
  346. *    seg_list = DevClose(request)
  347. *
  348. *    APTR DevClose(struct IOSana2Req *);
  349. *
  350. *   FUNCTION
  351. *
  352. *   INPUTS
  353. *
  354. *   RESULT
  355. *
  356. *   EXAMPLE
  357. *
  358. *   NOTES
  359. *
  360. *   BUGS
  361. *
  362. *   SEE ALSO
  363. *
  364. ****************************************************************************
  365. *
  366. */
  367.  
  368. static APTR DevClose(struct IOSana2Req *request REG("a1"),
  369.    struct DevBase *base REG(BASE_REG))
  370. {
  371.    struct DevUnit *unit;
  372.    APTR seg_list;
  373.    struct Opener *opener;
  374.  
  375.    /* Free buffer-management resources */
  376.  
  377.    opener=(APTR)request->ios2_BufferManagement;
  378.    if(opener!=NULL)
  379.    {
  380.       Disable();
  381.       Remove((APTR)opener);
  382.       Enable();
  383.       FreeVec(opener);
  384.    }
  385.  
  386.    /* Delete the unit if it's no longer in use */
  387.  
  388.    unit=(APTR)request->ios2_Req.io_Unit;
  389.    if(unit!=NULL)
  390.    {
  391.       if((--unit->open_count)==0)
  392.       {
  393.          Remove((APTR)unit);
  394.          DeleteUnit(unit,base);
  395.       }
  396.    }
  397.  
  398.    /* Expunge the device if a delayed expunge is pending */
  399.  
  400.    seg_list=NULL;
  401.  
  402.    if((--base->device.dd_Library.lib_OpenCnt)==0)
  403.    {
  404.       if((base->device.dd_Library.lib_Flags&LIBF_DELEXP)!=0)
  405.          seg_list=DevExpunge(base);
  406.    }
  407.  
  408.    return seg_list;
  409. }
  410.  
  411.  
  412.  
  413. /****i* 3c589.device/DevExpunge ********************************************
  414. *
  415. *   NAME
  416. *    DevExpunge -- .
  417. *
  418. *   SYNOPSIS
  419. *    seg_list = DevExpunge()
  420. *
  421. *    APTR DevExpunge();
  422. *
  423. *   FUNCTION
  424. *
  425. *   INPUTS
  426. *
  427. *   RESULT
  428. *
  429. *   EXAMPLE
  430. *
  431. *   NOTES
  432. *
  433. *   BUGS
  434. *
  435. *   SEE ALSO
  436. *
  437. ****************************************************************************
  438. *
  439. */
  440.  
  441. static APTR DevExpunge(struct DevBase *base REG(BASE_REG))
  442. {
  443.    APTR seg_list;
  444.  
  445.    if(base->device.dd_Library.lib_OpenCnt==0)
  446.    {
  447.       seg_list=base->seg_list;
  448.       Remove((APTR)base);
  449.       DeleteDevice(base);
  450.    }
  451.    else
  452.    {
  453.       base->device.dd_Library.lib_Flags|=LIBF_DELEXP;
  454.       seg_list=NULL;
  455.    }
  456.  
  457.    return seg_list;
  458. }
  459.  
  460.  
  461.  
  462. /****i* 3c589.device/DevReserved *******************************************
  463. *
  464. *   NAME
  465. *    DevReserved -- .
  466. *
  467. *   SYNOPSIS
  468. *    result = DevReserved()
  469. *
  470. *    APTR DevReserved();
  471. *
  472. *   FUNCTION
  473. *
  474. *   INPUTS
  475. *
  476. *   RESULT
  477. *
  478. *   EXAMPLE
  479. *
  480. *   NOTES
  481. *
  482. *   BUGS
  483. *
  484. *   SEE ALSO
  485. *
  486. ****************************************************************************
  487. *
  488. */
  489.  
  490. static APTR DevReserved()
  491. {
  492.    return NULL;
  493. }
  494.  
  495.  
  496.  
  497. /****i* 3c589.device/DevBeginIO ********************************************
  498. *
  499. *   NAME
  500. *    DevBeginIO -- .
  501. *
  502. *   SYNOPSIS
  503. *    DevBeginIO(request)
  504. *
  505. *    VOID DevBeginIO(struct IORequest *);
  506. *
  507. *   FUNCTION
  508. *
  509. *   INPUTS
  510. *
  511. *   RESULT
  512. *
  513. *   EXAMPLE
  514. *
  515. *   NOTES
  516. *
  517. *   BUGS
  518. *
  519. *   SEE ALSO
  520. *
  521. ****************************************************************************
  522. *
  523. */
  524.  
  525. static VOID DevBeginIO(struct IOSana2Req *request REG("a1"),
  526.    struct DevBase *base REG(BASE_REG))
  527. {
  528.    struct DevUnit *unit;
  529.  
  530.    request->ios2_Req.io_Error=0;
  531.    request->ios2_WireError=S2WERR_GENERIC_ERROR;
  532.    unit=(APTR)request->ios2_Req.io_Unit;
  533.  
  534.    if(AttemptSemaphore(&unit->access_lock))
  535.       ServiceRequest(request,base);
  536.    else
  537.    {
  538.       PutRequest(unit->request_ports[GENERAL_QUEUE],(APTR)request,base);
  539.    }
  540.  
  541.    return;
  542. }
  543.  
  544.  
  545.  
  546. /****i* 3c589.device/DevAbortIO ********************************************
  547. *
  548. *   NAME
  549. *    DevAbortIO -- Try to stop a request.
  550. *
  551. *   SYNOPSIS
  552. *    DevAbortIO(request)
  553. *
  554. *    VOID DevAbortIO(struct IOSana2Req *);
  555. *
  556. *   FUNCTION
  557. *    Do our best to halt the progress of a request.
  558. *
  559. *   INPUTS
  560. *
  561. *   RESULT
  562. *
  563. *   EXAMPLE
  564. *
  565. *   NOTES
  566. *
  567. *   BUGS
  568. *
  569. *   SEE ALSO
  570. *
  571. ****************************************************************************
  572. *
  573. * Disable() used instead of a semaphore because device uses interrupts.
  574. *
  575. */
  576.  
  577. static VOID DevAbortIO(struct IORequest *request REG("a1"),
  578.    struct DevBase *base REG(BASE_REG))
  579. {
  580.    struct DevUnit *unit;
  581.  
  582.    unit=(APTR)request->io_Unit;
  583.  
  584.    Disable();
  585.    if((request->io_Message.mn_Node.ln_Type==NT_MESSAGE)
  586.       &&((request->io_Flags&IOF_QUICK)==0))
  587.    {
  588.       Remove((APTR)request);
  589.       request->io_Error=IOERR_ABORTED;
  590.       ReplyMsg((APTR)request);
  591.    }
  592.    Enable();
  593.  
  594.    return;
  595. }
  596.  
  597.  
  598.  
  599. /****i* 3c589.device/DeleteDevice ******************************************
  600. *
  601. *   NAME
  602. *    DeleteDevice -- .
  603. *
  604. *   SYNOPSIS
  605. *    DeleteDevice()
  606. *
  607. *    VOID DeleteDevice();
  608. *
  609. *   FUNCTION
  610. *
  611. *   INPUTS
  612. *
  613. *   RESULT
  614. *
  615. *   EXAMPLE
  616. *
  617. *   NOTES
  618. *
  619. *   BUGS
  620. *
  621. *   SEE ALSO
  622. *
  623. ****************************************************************************
  624. *
  625. */
  626.  
  627. VOID DeleteDevice(struct DevBase *base)
  628. {
  629.    UWORD neg_size,pos_size;
  630.  
  631.    /* Close devices */
  632.  
  633.    CloseDevice((APTR)&base->timer_request);
  634.  
  635.    /* Close libraries */
  636.  
  637.    if(base->pccard_base!=NULL)
  638.       CloseLibrary(base->pccard_base);
  639.    if(base->utility_base!=NULL)
  640.       CloseLibrary((APTR)base->utility_base);
  641.  
  642.    /* Free device's memory */
  643.  
  644.    neg_size=base->device.dd_Library.lib_NegSize;
  645.    pos_size=base->device.dd_Library.lib_PosSize;
  646.    FreeMem((UBYTE *)base-neg_size,pos_size+neg_size);
  647.  
  648.    return;
  649. }
  650.  
  651.  
  652.  
  653.